package com.tree.common.interceptor;

import com.tree.common.annotation.ResponseResult;
import com.tree.common.dto.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import javax.servlet.http.HttpServletRequest;

/**
 * @ClassName com.tree.common.interceptor
 * Description: 统一处理返回对象
 * <p>
 * 统一处理返回对象， 如果已经被包装为Result对象， 则不处理， 否则包装
 * </p>
 * @Author tree
 * @Date 2020-03-29 00:09
 * @Version 1.0
 */
@Slf4j
@RestControllerAdvice
public class ResponseResultHandler implements ResponseBodyAdvice<Object> {
    /**
     * 标记名称
     */
    public static final String RESPONSE_RESULT_MARK = "RESPONSE_RESULT_MARK";

    /**
     * 是否请求包含了包装注解标记，没有就直接返回，不需要重写返回体
     * @param returnType
     * @param converterType
     * @return
     */
    @Override
    public boolean supports(MethodParameter returnType,
                            Class<? extends HttpMessageConverter<?>> converterType) {
        ServletRequestAttributes sra = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = sra.getRequest();
        //判断请求是否有标记
        ResponseResult responseResult = (ResponseResult) request.getAttribute(RESPONSE_RESULT_MARK);
        return responseResult == null ? false:true;
    }

    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
        //如果已经被包装为Result（1. 正常返回对象 2. 异常对象，即ExceptionHandlerController处理的对象）， 不做处理直接返回
        if(body instanceof Result){
            return body;
        }else {
            return Result.success(body);
        }
    }
}
